#include <iostream>
#include <thread>
#include <functional>

using std::cout;
using std::endl;
using std::thread;
using std::function;
using std::bind;

void func(int x){
    cout << "x = " << x << endl;
}
//普通函数作为线程入口函数
void test1(){
    thread th1(func,2);
    th1.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
//函数指针作为线程入口函数
void test2(){
    //下面两种写法都可以，第二种就是重新命名
    /* void (*pfunc)(int); */
    /* pfunc = &func; */
    /* thread th2(pfunc,2); */
    typedef void (*pfunc)(int);
    pfunc f= &func;//这里加不加&都可以，
                   //因为func函数名隐式类型转换成地址（函数指针）
    thread th2(f,2);
    th2.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
//函数引用作为线程入口函数
void test3(){
    typedef void (&pfunc)(int);
    pfunc f= func;
    thread th3(f,2);
    th3.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
//成员函数作为线程入口函数
class Example{
public:
    void efunc(int x){
        cout << "x = " << x << endl;
    }
};
void test4(){
    Example ex;
    thread th4(&Example::efunc,&ex,4);//这里ex前面加不加&是看他是怎么传入的
                                      //带&就是地址传入，只传入指针大小
                                      //不带地址就是值传递，需要拷贝一个副本传进去
    th4.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));

}
//函数对象作为线程入口函数
class Example2{
public:
    //为什么要重载operator()
    //让对象具有函数的行为（即可被调用），同时又能携带状态（成员变量），
    //这样在需要可调用对象的地方（如线程入口、STL算法等）可以灵活地传递具有状态的函数对象，
    //实现比普通函数更复杂的功能，同时保持高效和易用性。
    void operator()(int x){
        cout << "x = " << x << endl;
    }
};
void test5(){
    Example2 ex;
    thread th5(ex,5);
    th5.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
//lambda表达式作为线程入口函数
void test6(){
    thread th6([](int x){
               cout << "x = " << x << endl;
               },6);
    th6.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
//function作为线程入口函数
void test7(){
    function<void(int x)> f = [](int x){
               cout << "x = " << x << endl;
    };
    thread th7(f,7);
    th7.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));
};
//bind作为线程入口函数
void test8(){
    thread th8(bind(func,8));
    th8.join();
    std::this_thread::sleep_for(std::chrono::seconds(1));
}


int main()
{
    test8();
    return 0;
}

